/*
 * CSVector.hpp
 *
 * Copyright 2013 Fabian Wenzelmann
 *
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 *
 * Recognition-Procedures-for-Boolean-Functions is free software: you
 * can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.
 *
 * If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef CSVECTOR_HPP_
#define CSVECTOR_HPP_

#include <algorithm>
#include <vector>
// size_t
#include <string>

namespace bfr {

template <class T>
class CSVector {

    public:
        typedef typename std::vector<T> clause_t;
        typedef typename std::vector<clause_t> content_t;
        typedef typename clause_t::const_iterator clause_iterator;
        typedef typename content_t::const_iterator const_iterator;

        CSVector()
            : content() { };
        CSVector(size_t initialSize)
            : content() {
            content.reserve(initialSize);
        }

        template<class InputIterator>
        CSVector(InputIterator first, InputIterator last)
            : content(first, last) { }

        ~CSVector() { }

        size_t size() const {
            return content.size();
        }

        size_t addClause(const std::vector<T> &clause) {
            size_t pos = size();
            content.push_back(clause);
            return pos;
        }

        size_t addClause() {
            std::vector<T> clause;
            return addClause(clause);
        }

        const_iterator begin() const {
            return content.begin();
        }

        const_iterator end() const {
            return content.end();
        }

        void addToClause(size_t clause, const T &item) {
            content[clause].push_back(item);
        }

        const clause_t &getClause(size_t id) const {
            return content[id];
        }

        clause_t &getClause(size_t id) {
            return content[id];
        }

        void sortClause(clause_t &clause) {
            std::sort(clause.begin(), clause.end());
        }

        void sortClause(size_t clauseID) {
            sortClause(getClause(clauseID));
        }

        template<class ClauseType>
        friend std::ostream& writeClause(std::ostream& os, const ClauseType &c) {
            if (c.size() == 0) {
                os << "{}";
            }
            else {
                os << '{';
                typename ClauseType::const_iterator it = c.begin();
                os << *it;
                ++it;
                while (it != c.end()) {
                    os << ", " << *it;
                    ++it;
                }
                os << '}';
            }
            return os;
        }

        template<class ItemT>
        friend std::ostream& operator<<(std::ostream& os, const CSVector<ItemT> &c) {
            if (c.size() == 0 )
                os << "{}";
            else {
                os << '{';
                typename CSVector<ItemT>::const_iterator it = c.begin();
                writeClause(os, *it);
                ++it;
                while (it != c.end()) {
                    os << ", ";
                    writeClause(os, *it);
                    ++it;
                }
                os << '}';
            }
            return os;
        }

    private:
        content_t content;


};

typedef CSVector<size_t> PosCS;

} /* namespace bfr */

#endif  // CSVECTOR_HPP_
